using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Tool
{
    public class Modbus:ViewModelBase
    {
        private string address;//地址码
        private string function;//功能码
        private string start;//数据起始地址
        private string count;//数据元素个数

        public string Address { 
            get => address;
            set 
            { 
                address = value;
                RaisePropertyChanged("Address");
            }
        }
        public string Function {
            get => function;
            set
            {
                function = value;
                RaisePropertyChanged("Function");
            }
        }
        public string Start { 
            get => start;
            set
            {
                start = value;
                RaisePropertyChanged("Start");
            }
        }
        public string Count { 
            get => count;
            set
            {
                count = value;
                RaisePropertyChanged("Count");
            }
        }
        /// <summary>
        /// Function: generate Modbus code
        /// </summary>
        /// <param name="address"></param>
        /// <param name="function"></param>
        /// <param name="start"></param>
        /// <param name="count"></param>
        /// <returns></returns>
        public List<byte> GenerateCode(string address,string function,string start,string count)
        {
            string result=address+function+start+count;
            List<byte> hex = HexToBytes(result);
            List<byte> crc16=GenerateCRC16(hex, hex.Count);//hex.Count为字节数
            hex.AddRange(crc16);//拼接List实例
            return hex;
        }
        /// <summary>
        /// Function: Converter from Hex to List bytes
        /// </summary>
        /// <param name="hex"></param>
        /// <returns></returns>
        public List<byte> HexToBytes(string hex)
        {
            List<byte> bytes = new List<byte>();
            for(int i=0;i<hex.Length;i+=2)//遍历字符串中的字符
            {
                string subStr = hex.Substring(i, 2);
                bool flag=byte.TryParse(hex.Substring(i,2), System.Globalization.NumberStyles.AllowHexSpecifier, null ,out byte temp);
                bytes.Add(temp);
            }
            return bytes;
        }
        /// <summary>
        /// Function: calculate CRC16
        /// Input: data for calculate, data length(count of bytes)
        /// Output: value of CRC16 
        /// </summary>
        /// <param name="data"></param>
        /// <param name="dataLen"></param>
        /// <returns></returns>
        public List<byte> GenerateCRC16(List<byte> data,int bytesLen)
        {
            int i, j;//循环变量
            ushort regCRC = 0xFFFF;//用于保存CRC值
            List<byte> result = new List<byte>();
            for (i = 0; i < bytesLen; i++)//循环处理传输缓冲区消息
            {
                regCRC ^= data[i];//异或算法得到CRC值
                for (j = 0; j < 8; j++)//循环处理每个bit位
                {
                    int tmp = regCRC & 1;
                    regCRC >>= 1;
                    regCRC &= 0x7FFF;
                    if (1==tmp)
                    {
                        regCRC ^= 0xA001;
                    }
                    regCRC &= 0xffff;
                }
            }
            result = BitConverter.GetBytes(regCRC).ToList<byte>();//ushort to byte[]
            return result;
        }
    }
    public class FunctionCode:INotifyPropertyChanged
    {
        private string code;
        private string meaning;

        public string Code { 
            get => code;
            set
            {
                code = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("Code"));
                }
            }
        }
        public string Meaning { 
            get => meaning;
            set 
            { 
                meaning = value;
                if (this.PropertyChanged != null)
                {
                    this.PropertyChanged(this, new PropertyChangedEventArgs("Meaning"));
                }
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
    }
}
